home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / rwvector.lha / RWVector2.1 / README < prev   
Text File  |  1989-08-18  |  14KB  |  339 lines

  1.  
  2.     The ROGUE WAVE Vector and Matrix Classes.
  3.                 Version 2
  4.  
  5.       Copyright (C) 1988, 1989.
  6.   
  7.       Dr. Thomas Keffer
  8.       Rogue Wave Associates
  9.       P.O. Box 85341
  10.       Seattle WA 98145-1341
  11.   
  12.       Permission to use, copy, modify, and distribute this
  13.       software and its documentation for any purpose and
  14.       without fee is hereby granted, provided that the
  15.       above copyright notice appear in all copies and that
  16.       both that copyright notice and this permission notice
  17.       appear in supporting documentation.
  18.       
  19.       This software is provided "as is" without any
  20.       expressed or implied warranty.
  21.   
  22. *********************************************************************
  23.  
  24.     ******  A C K N O W L E D G E M E N T S  ******
  25.  
  26. I am indebted to Al Vermeulen (Univ. of Waterloo) for his insightful
  27. feedback and debugging.  The critical idea of implementing all vectors
  28. as slices was also his.
  29.  
  30. *********************************************************************
  31.  
  32.     ******  O V E R V I E W  ******
  33.  
  34. This is a set of vector and matrix classes.  Right now it includes all
  35. standard arithmetic operations (+, *, /, -, --, etc.) for types
  36. double, float, int, and complex, and most math functions (sin, cos,
  37. sum, cumsum, etc.).  The Vector classes include three FFT "server"
  38. classes:
  39.  
  40. 1) DComplexFFTServer which can transform a complex vector
  41.    into a complex vector (and back).
  42.  
  43. 2) DoubleFFTServer which transforms a real vector into a complex
  44.    conjugate even vector (and back).
  45.  
  46. 3) DCosineFFTServer which performs sine and cosine transforms.  That
  47.    is, it can transform either a real even or a real odd vector into a
  48.    real even or odd vector (respectively).
  49.  
  50. The Matrix classes include an LU decomposition class (both double and
  51. float) which can perform matrix inversions, solve systems of linear
  52. equations, and calculate determinants.
  53.  
  54. The overall goal of the classes is to be as simple as possible while
  55. not sacrificing (too much) in the way of speed.  Because it is easy to
  56. generate absolutely huge header files and very long compilation times
  57. when working with C++, simplicity is important.  Extendability is also
  58. important.  Others are working on more exotic vector classes that
  59. avoid the use of temporaries by building expression trees at runtime
  60. and then optimizing them out.  No doubt these will be fast, but they
  61. will also be very complicated, big, and hard to extend.
  62.  
  63. The classes here do not avoid using temporaries, but use reference
  64. counting to minimize the time required for their construction.  They
  65. should give you 90% of the speed of a more optimal package
  66. (particulary when doing floating point intensive operations like
  67. matrix inversion) with about a quarter of the size and compilation
  68. times.  Example: the test program for LU decomposition (dludtest),
  69. using g++, is only 90k bytes long (stripped).
  70.  
  71. The classes have been designed to be compatible with the NIH Vector
  72. classes.  Indeed, they have the same names and many of the same
  73. functions and syntax.  They implement "slices", but not "picks" and
  74. "selections" (I have not found the last two very useful).  One
  75. significant difference: a slice is taken with a slice() function,
  76. rather than an overloaded operator().  I have found the latter
  77. confusing.  Hence, use:
  78.     a.slice(0,3,1)
  79. instead of
  80.     a(0,3,1)
  81.  
  82. The resulting syntax is very powerful.  For example:
  83.  
  84.     DGEMatrix a(4,4,0);           // A 4x4 matrix initialized to 0
  85.     a.diagonal() = 1;             // Set the diagonal to 1
  86.     a.diagonal(-1) = 2;           // Set the lower diagonal to 2
  87.     a.row(2) = -1;                // Set row 2 to -1
  88.     DGEMatrix ainv = inverse(a);  // Invert a
  89.  
  90. Note that many functions can be used as an lvalue.  This is also true
  91. of vector slices.  Here's an example.  Use the Complex FFT Server to
  92. verify Parseval's theorem at the Nyquist frequency.  It makes a good
  93. example because it both uses slices and the FFT Server:
  94.  
  95.     DComplexFFTServer server;    // Construct the server
  96.  
  97.     // Make a test series, npts long, initialized to complex(1,1)
  98.     DComplexVec Nyquist(npts, DComplex(1.0, 1.0));
  99.  
  100.     // Set every other element to complex(-1, -1):
  101.     Nyquist.slice(1,npts/2,2) = DComplex(-1.0, -1.0));
  102.  
  103.     // Take its fourier transform:
  104.     DComplexVec transform = server.fourier(Nyquist)/npts;
  105.  
  106.     // Calculate its original variance
  107.     cout << variance(Nyquist) <<"\n";
  108.  
  109.     // Compare to the final, spectral variance:
  110.     cout << spectralVariance(transform) <<"\n";    
  111.  
  112. The use of slices can virtually eliminate the "for" loop over vector
  113. and matrix elements.  This makes it easier to port the resulting code
  114. to an array processory or other specialized hardware.  Or, a Basic
  115. Linear Algebra (BLA) package can be used.
  116.  
  117. The test suite has many examples for using the classes.
  118.  
  119. *********************************************************************
  120.  
  121.     *******  Changes from Version 1  *******
  122.         (not necessary to read right now)
  123.  
  124. The biggest changes from Version 1 is the addition of matrix classes
  125. and the elimination of the Slice temporaries (e.g., "DoubleSlice").
  126. Many small improvements were also made.
  127.  
  128. All vectors are now treated as slices.  This should be mostly
  129. transparent to you.  This approach drastically reduces the number of
  130. routines that must be written, the size of the code, and the number of
  131. type conversions that have to be done at runtime.  It also makes type
  132. conversions more reliable and obvious.  The one curious side effect
  133. (as it turns out) is that you must pay attention to the very real
  134. difference (in C++) between initialization and assignment:
  135.  
  136.     DoubleVec a, b, c;
  137.     DoubleVec d = a;   // Note: d will be a REFERENCE to a
  138.     d = b;             // Note: d will contain a COPY of b
  139.     d.reference(c);    // Note: d will be a reference to d
  140.  
  141. Note that copy initialization is done by referencing the new variable
  142. to the contents of the old variable, but assignment is done by COPYING
  143. the contents over.  The function reference() is provided because a
  144. variable can be initialized only once, subsequent assignments will
  145. provide only copies.  It will simulate the effects of initialization.
  146. The overall effect is that boths sides of an assignment MUST have the
  147. same size.  Both variables need not have the same size when using
  148. reference() (the object taking the reference will be resized to the
  149. argument).  
  150.  
  151. Why use a reference?  Speed.  They are used by the temporaries to
  152. avoid unnecessary copying of the bulk of the vector.
  153.  
  154. *********************************************************************
  155.  
  156.     ******  I N S T A L L A T I O N  ******
  157.  
  158. The Classes can be compiled with either the GNU "g++" compiler
  159. (version 1.35 or later) or the AT&T "cfront" compiler (Version 1.2, or
  160. Version 2.0).  If the GNU compiler is used, then the class Complex, as
  161. defined in the header file Complex.h distributed with the GNU g++
  162. library is used for complex arithmetic.  If one of the AT&T compilers
  163. is used, then class complex, as defined in complex.h is used.
  164. However, the complex.h distributed with the V1.2 compiler cannot be
  165. used to make vectors of complex: it has no unadorned constructor.  I
  166. have included a revised version of complex.h in this distribution
  167. which will automatically be used if you are using the 1.2 compiler.
  168. The 2.0 version of complex has the necessary constructor.
  169.  
  170. 0) Glance through the "Pitfalls" section below, just so you know
  171. where the holes are.  Here's a language that's not even 5 years old,
  172. and already there's no way to write a standard package!
  173.  
  174. 1) Makefiles are provided for the GNU compiler (the default) and the
  175. AT&T "cfront" compiler (Makefile.ATT).  Select the proper makefile.
  176.  
  177. 2) AT&T compiler only:
  178.  
  179.    You might want to remove the #pragma statements in the files rw/*.h,
  180.    if you don't want to look at warning errors.  There are two shell
  181.    scripts for doing this: "depragmatize" to remove the #pragma statements,
  182.    "pragmatize" to put them back in.
  183.  
  184.    Set the define near the top of Makefile.ATT to select either __ATT1__
  185.    if you are using the 1.2 compiler, or __ATT2__ if you are using the
  186.    version 2.0 compiler.
  187.  
  188.    Check the tail end of Makefile.ATT ("Conversions") to make sure
  189.    that it is expecting the proper suffixes for your CC driver script.
  190.    Mine accepts .C, puts out .C.o.  Yours might differ.
  191.  
  192.    You will have to set your environment variables as usual.
  193.  
  194. 2) Make sure that the proper floating point options are selected for
  195. your hardware in the appropriate Makefile.
  196.  
  197. 3) As distributed, the GNU version 1.35.0 include file math.h does not
  198. overload atan().  Version 1.35.1 does.  You might want to add this
  199. entry.
  200.  
  201. 4) The FFT functions depend on a fortran package from the National
  202. Center for Atmospheric Research to do the actual FFT.  They are a lot
  203. more complicated than some other routines, but they offer two
  204. advantages: They let you do FFTs on vectors of arbitrary length (not
  205. just powers of two), and they vectorize very nicely.  If you are
  206. unable to compile the fortran routines (or don't want to!) then you
  207. will be unable to run the full test suite.  Programs testdfft,
  208. testcfft, and testcos require mathpack.  Or, you can supply your own
  209. FFT routines.  A routine that transforms a complex vector into a
  210. complex vector and back is all that is required.  All other transforms
  211. (real to conjugate even, cosine transforms, etc.) sit on top of it.
  212. These routines are put in a library called libmathpack.a.  If someone
  213. has got a C++ (or C) function to do arbitrary length FFTs, I'd be
  214. delighted to put it in.
  215.  
  216. 5) The linear algebra stuff (LU decomposition, matrix inversion), etc.
  217. are based on LINPACK, and also put in the library libmathpack.a (see
  218. point 4 above).  Again, if you don't want to, or can't compile them,
  219. then you will be unable to use the linear algebra routines.  Programs
  220. dludtest and fludtest require these routines.  I decided to use
  221. LINPACK because they are well know, robust, trusted, and have
  222. assembler versions of their Basic Linear Algebra package.
  223.  
  224. 6) cd to the src directory, then type make:
  225.  
  226.     cd src
  227.     make
  228.  
  229. With the GNU compiler, you will get a slew of warning messages, due to
  230. the inline nature of the GNU math library.  Here's a sample:
  231.  
  232. In function struct DoubleVec asin (const struct DoubleSlice &):
  233. ./../rw/DoubleVec.h:228: warning: argument passing of non-const * pointer from const *
  234.  
  235. 7) To make the mathpack library (libmathpack.a), in the same src
  236. directory, type
  237.  
  238.     make mathpack
  239.  
  240. 8) To make the test suite, in the src directory, type
  241.  
  242.     make test
  243.  
  244. 9) To verify it:
  245.  
  246.     make verify
  247.  
  248. I have tried to design the test suite so that variations at the
  249. machine precision will not be apparent, but I may not have been
  250. entirely successful.  In particular, the g++ and cfront formatting
  251. differ slightly.
  252.  
  253. 9) Finally, to install the package, check the Makefile macros LIBDIR,
  254. and INCLDIR to see if the default installation locations suit you, then
  255.  
  256.     make install
  257.  
  258.  
  259. **********************************************************************
  260.  
  261.     ******  P I T F A L L S  ******
  262.  
  263. * Most of the FFT routines *require* that
  264.     sizeof(Complex) == 2 * sizeof(double)
  265. in order to pass arguments correctly to the Fortran FFT routines.
  266. This will be true provided:
  267.  
  268.     a) Structures can align on a double boundary (hard to imagine
  269.     a machine where this isn't true);
  270.     b) There are no other member objects in Complex besides the 
  271.     two doubles (i.e., real and imaginary);
  272.     c) No base class in Complex;
  273.     d) No virtual functions in Complex.
  274.     e) Your compiler does not add any hidden data to the Complex
  275.     class.  Neither the GNU nor the AT&T compilers do this.  Note,
  276.     however, that this is NOT part of the language definition!
  277.  
  278. All of these conditions apply for both the GNU g++ Complex, and
  279. Stroustrup's complex class and you shouldn't have any trouble.
  280. Undefine the macro "COMPLEX_PACKS" in RComplex.h if one of these
  281. conditions does not hold: Some of the routines have workarounds.
  282. Others curl up and die.
  283.  
  284. * My version of the GNU loader (gcc-ld++) is unreliable in finding all
  285. referenced externals.  For example, for a while it had trouble finding
  286. "hypot.o" (which is in /usr/lib/libm.a).  If this happens to you, you
  287. will have to extract the lost module and add it by hand to the TARGET
  288. link list:
  289.  
  290.     ar x /usr/lib/libm.a hypot.o
  291.  
  292. (then change the TARGET entry in the Makefile to:)
  293.  
  294. ${TARGET}:   ${TARGET}.o ${LIBFILE} ${MATHLIB}
  295.     ${CCXX} ${CXXFLAGS} -o ${TARGET} ${TARGET}.o hypot.o ${LIBFILE} ${MATHLIB} -lm
  296.                                                  ~~~~~~~
  297.  
  298. This bug has been reported.
  299.  
  300. * The file complex.h as distributed with the AT&T Version 1.2 compiler
  301. cannot be used to make vectors of type complex.  This is because it
  302. does not include an unadorned constructor complex::complex().  Hence,
  303. I have modified the file and included it.  It is used only if the
  304. Version 1 cfront compiler is used.  If the GNU compiler is used, then
  305. the file Complex.h, as distributed with the GNU library, is used.  If
  306. Version 2 of cfront is used then the version distributed with it is
  307. used.  
  308.  
  309. * Both compilers are touchy about inlines and type conversions.
  310. Workarounds have been included.  In particular, the Version 1.2 cfront
  311. compiler seems to have trouble with inlines nestled more than one
  312. deep.
  313.  
  314. * I have not tried optimization flags with the routines.  I have no
  315. idea if this would introduce compiler bugs.
  316.  
  317. * The AT&T version 1.2 compiler has trouble assigning a real to an
  318. element of a complex vector.  Example:
  319.  
  320.     DComplexVec a(10);
  321.     a(3) = 2.0;
  322.  
  323. will give a "bus error" (whatever that is).  The cure is to switch to
  324. the GNU compiler.  No. Seriously.  Use a cast.  The last line should
  325. be written as:
  326.  
  327.     a(3) = DComplex(2.0);
  328.  
  329.  
  330.     ******  B U G   R E P O R T S  ******
  331.  
  332. Send 'em to:
  333.  
  334.  Dr. Thomas Keffer          | Internet: keffer@sperm.ocean.washington.edu
  335.  School of Oceanography     | BITNET:   keffer%sperm.ocean.washington.edu@UWAVM
  336.  Univ. of Washington, WB-10 | uucp:     uw-beaver!sperm.ocean.washington.edu!keffer
  337.  Seattle, WA 98195          | Telemail: T.KEFFER/OMNET
  338.     (206) 543-6455
  339.